package com.ruoyi.demo.controller;

import io.minio.*;
import io.minio.errors.MinioException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;

/**
 * 视频流控制器
 */
@Slf4j
@RestController
@RequestMapping("/demo/stream")
public class VideoStreamController {

    @Autowired
    private MinioClient minioClient;

    /**
     * 流式播放视频
     *
     * @param meetId   会议ID
     * @param filename 文件名
     * @param request  HTTP请求
     * @return 视频流响应
     */
    @GetMapping("/video")
    public ResponseEntity<Resource> streamVideo(
            @RequestParam Long meetId,
            @RequestParam String filename,
            HttpServletRequest request) {

        log.info("接收到视频流请求: meetId={}, filename={}", meetId, filename);

        try {
            // 构建完整的文件路径
            String filePath = String.format("meet/%d/agendaVideo/%s", meetId, filename);
            String bucketName = "project";

            log.info("开始获取 MinIO 文件: bucket={}, path={}", bucketName, filePath);

            // 检查文件是否存在
            StatObjectResponse stat = minioClient.statObject(
                    StatObjectArgs.builder()
                            .bucket(bucketName)
                            .object(filePath)
                            .build()
            );

            log.info("文件信息: size={}, contentType={}", stat.size(), stat.contentType());

            // 获取文件流
            InputStream inputStream = minioClient.getObject(
                    GetObjectArgs.builder()
                            .bucket(bucketName)
                            .object(filePath)
                            .build()
            );

            // 创建资源
            InputStreamResource resource = new InputStreamResource(inputStream);

            // 设置响应头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.parseMediaType("video/mp4"));
            headers.setContentLength(stat.size());
            headers.set(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + filename + "\"");
            headers.set(HttpHeaders.ACCEPT_RANGES, "bytes");

            // 处理范围请求
            String rangeHeader = request.getHeader(HttpHeaders.RANGE);
            if (rangeHeader != null && rangeHeader.startsWith("bytes=")) {
                try {
                    String[] ranges = rangeHeader.substring(6).split("-");
                    long start = Long.parseLong(ranges[0]);
                    long end = ranges.length > 1 && !ranges[1].isEmpty()
                            ? Long.parseLong(ranges[1])
                            : stat.size() - 1;

                    // 确保范围有效
                    end = Math.min(end, stat.size() - 1);
                    long contentLength = end - start + 1;

                    log.info("处理范围请求: start={}, end={}, total={}", start, end, stat.size());

                    headers.set(HttpHeaders.CONTENT_RANGE,
                            String.format("bytes %d-%d/%d", start, end, stat.size()));
                    headers.setContentLength(contentLength);

                    // 跳过不需要的数据
                    inputStream.skip(start);

                    return ResponseEntity.status(HttpStatus.PARTIAL_CONTENT)
                            .headers(headers)
                            .body(resource);
                } catch (NumberFormatException | IOException e) {
                    log.error("处理范围请求失败", e);
                }
            }

            log.info("返回完整视频文件");
            return ResponseEntity.ok()
                    .headers(headers)
                    .body(resource);

        } catch (MinioException e) {
            log.error("MinIO 操作失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(null);
        } catch (Exception e) {
            log.error("视频流处理失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(null);
        }
    }

    /**
     * 音频流播放
     *
     * @param meetId   会议ID
     * @param filename 文件名
     * @param request  HTTP请求
     * @return 音频流响应
     */
    @GetMapping("/audio")
    public ResponseEntity<Resource> streamAudio(
            @RequestParam Long meetId,
            @RequestParam String filename,
            HttpServletRequest request) {

        log.info("接收到音频流请求: meetId={}, filename={}", meetId, filename);

        try {
            // 构建完整的文件路径
            String filePath = String.format("meet/%d/agendaAudio/%s", meetId, filename);
            String bucketName = "project";

            log.info("开始获取 MinIO 文件: bucket={}, path={}", bucketName, filePath);

            // 检查文件是否存在
            StatObjectResponse stat = minioClient.statObject(
                    StatObjectArgs.builder()
                            .bucket(bucketName)
                            .object(filePath)
                            .build()
            );

            log.info("文件信息: size={}, contentType={}", stat.size(), stat.contentType());

            // 获取文件流
            InputStream inputStream = minioClient.getObject(
                    GetObjectArgs.builder()
                            .bucket(bucketName)
                            .object(filePath)
                            .build()
            );

            // 创建资源
            InputStreamResource resource = new InputStreamResource(inputStream);

            // 设置响应头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.parseMediaType("audio/mpeg"));
            headers.setContentLength(stat.size());
            headers.set(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + filename + "\"");

            return ResponseEntity.ok()
                    .headers(headers)
                    .body(resource);

        } catch (MinioException e) {
            log.error("MinIO 操作失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(null);
        } catch (Exception e) {
            log.error("音频流处理失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(null);
        }
    }
}